﻿#ifndef __SS_ATOMIC_H__
#define __SS_ATOMIC_H__

#ifdef _WIN32
#include <Windows.h>
#define SS_ATOMIC_SET(ptr,val) InterlockedExchange(ptr,val)
#define SS_ATOMIC_INC(ptr) InterlockedIncrement(ptr)
#define SS_ATOMIC_DEC(ptr) InterlockedDecrement(ptr)
#define SS_ATOMIC_ADD(ptr,val) InterlockedExchangeAdd(ptr,val)
#define SS_ATOMIC_CAS(ptr,comp,exc) InterlockedCompareExchange(ptr,exc,comp)
#else
#include <unistd.h>
#define SS_ATOMIC_SET(ptr,val) __sync_lock_test_and_set(ptr,val)
#define SS_ATOMIC_INC(ptr) __sync_add_and_fetch(ptr,1)
#define SS_ATOMIC_DEC(ptr) __sync_sub_and_fetch(ptr,1)
#define SS_ATOMIC_ADD(ptr,val) __sync_fetch_and_add(ptr,val)
#define SS_ATOMIC_CAS(ptr,comp,exc) __sync_val_compare_and_swap(ptr,comp,exc)
#endif

namespace StarSeeker
{

template<typename T_ATOMIC>//类型只能用int32和int64或者他们的无符号类型
class ssAtomic
{
	friend class ssAtomicLock;
public:
	explicit ssAtomic(T_ATOMIC n=0)
	{
		SS_ATOMIC_SET(&m_available, n);
	}

	T_ATOMIC operator ++()
	{
		return SS_ATOMIC_INC(&m_available);
	}
	T_ATOMIC operator --()
	{
		return SS_ATOMIC_DEC(&m_available);
	}
	T_ATOMIC operator +=(T_ATOMIC n)
	{
		T_ATOMIC ret = SS_ATOMIC_ADD(&m_available, n);
		return ret+n;
	}
	T_ATOMIC operator -=(T_ATOMIC n)
	{
		T_ATOMIC ret = SS_ATOMIC_ADD(&m_available, -n);
		return ret - n;
	}
	T_ATOMIC operator =(T_ATOMIC n)
	{
		SS_ATOMIC_SET(&m_available, n);
		return n;
	}
	T_ATOMIC CompareExchange(T_ATOMIC comp, T_ATOMIC exc)
	{
		return SS_ATOMIC_CAS(&m_available, comp, exc);
	}
	bool operator ==(ssAtomic n) const
	{
		return m_available == n.m_available;
	}
	bool operator !=(ssAtomic n) const
	{
		return m_available != n.m_available;
	}
	bool operator ==(T_ATOMIC n) const
	{
		return m_available == n;
	}
	bool operator !=(T_ATOMIC n) const
	{
		return m_available != n;
	}
	bool operator >(ssAtomic n) const
	{
		return m_available > n.m_available;
	}
	bool operator <(ssAtomic n) const
	{
		return m_available < n.m_available;
	}
	bool operator >(T_ATOMIC n) const
	{
		return m_available > n;
	}
	bool operator <(T_ATOMIC n) const
	{
		return m_available < n;
	}
	T_ATOMIC Value() const
	{
		return m_available;
	}
private:
	ssAtomic(const ssAtomic&);
	ssAtomic operator =(ssAtomic&);
private:
	volatile T_ATOMIC	m_available;
};
typedef ssAtomic<long> ssAtomicl;

}
#endif
